package com.menghao.log.aop;

import com.menghao.log.enums.FieldEnum;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * <p>切面类.<br>
 *
 * @author menghao.
 * @version 2017/11/30.
 */
@Aspect
public class LogAspect {

    private static final Logger log = LoggerFactory.getLogger(LogAspect.class);

    private List<FieldEnum> fieldEnums;

    public LogAspect(List<FieldEnum> fieldEnums) {
        this.fieldEnums = fieldEnums;
    }

    /**
     * 被注解标注的方法
     */
    @Pointcut("@annotation(com.menghao.log.annotation.MethodLog)")
    public void method() {
    }

    /**
     * 被注解标注的类下所有方法
     */
    @Pointcut("@within(com.menghao.log.annotation.MethodsLog)")
    public void methods() {
    }

    /**
     * 前置日志记录
     */
    @Before("method() || methods()")
    public void logBefore(JoinPoint joinPoint) {
        if (fieldEnums.contains(FieldEnum.BEFORE)) {
            HttpServletRequest request =
                    ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String ip = request.getRemoteAddr();
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Object[] args = joinPoint.getArgs();
            log.info("来自[{}]访问类：[{}],方法：[{}],参数：{}",
                    ip, className, methodName, args);
        }
    }

    /**
     * 异常日志记录
     */
    @AfterThrowing(pointcut = "method() || methods()", throwing = "e")
    public void logException(JoinPoint joinPoint, Throwable e) {
        if (fieldEnums.contains(FieldEnum.EXCEPTION)) {
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Object[] args = joinPoint.getArgs();
            log.error("访问类：[{}],方法：[{}],参数：{},异常类型：[{}],异常信息：[{}]",
                    className, methodName, args, e.getClass().getName(), e.getMessage());
        }
    }

    /**
     * 返回结果日志记录
     */
    @AfterReturning(pointcut = "method() || methods()", returning = "result")
    public void logReturn(JoinPoint joinPoint, Object result) {
        if (fieldEnums.contains(FieldEnum.RETURN)) {
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Object[] args = joinPoint.getArgs();
            log.info("访问类：[{}],方法：[{}],参数：{},返回值：[{}]",
                    className, methodName, args, result);
        }
    }
}
